/**
 * flightReservation package contains classes that enable
 * users to make reservations with a particular airline
 */
package flightReservation;

import flightSerialization.*;

import java.io.IOException;
import java.io.OptionalDataException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;

/**
 *
 *
 */
public class Flight implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private String flightNo;
	private String origin;
	private String destination;
	private Date depTime;
	private Date arrTime;

	private ArrayList<Seat> seatList;
	//private ArrayList<Passenger> passengerList;
	private ArrayList<Passenger> waitingList;
	private ArrayList<Reservation> reservationList;
	Passenger seatArray[][];
	private int maxRows;
    private int maxSeatPerRow;
	private int seatsLeft;
	String colName;
	int rowNumber;
	int columnnumber;
	public static String cols =  "ABCDEF";
	static String fileName = "C:\\flightReservation3.ser";
	private String currentReservationNo;
	/**
	 * 
	 */
	public Flight() {

	}
	public Flight(String flightNo, String origin, String destination, Date depTime, Date arrTime) {
		this.flightNo = flightNo;
		this.origin = origin;
		this.destination = destination;
		this.depTime = depTime;
		this.arrTime = arrTime;
		
		maxRows = 2;
        maxSeatPerRow = 4;
        seatsLeft = maxRows * maxSeatPerRow;
        seatArray = new Passenger[maxRows][maxSeatPerRow];
	}
	
	public String getFlightNumber() {
		return this.flightNo;
	}
	
	public String getOrigin() {
		return this.origin;
	}

	public String getDestination() {
		return this.destination;
	}
	
	public Date getDeptTime()
	{
		return this.depTime;
	}
	
	public Date getArrTime()
	{
		return this.arrTime;
	}
	
	public Passenger[][] getSeatArray() {
        return seatArray;
    }
	
	public ArrayList<Seat> getSeatList() {
		if(seatList == null)
		{
			seatList = new ArrayList<Seat>();
		}
        return seatList;
    }

	public int getMaxrows() {
        return maxRows;
    }

    public int getMaxSeatPerRow() {
        return maxSeatPerRow;
    }
    
    public int getSeatsLeft() {
        return seatsLeft;
    }

	/**
	 * 
	 */
	public ArrayList<Reservation> viewReservations() {
		
		return this.reservationList;
	}
	
	/**
	 * Returns an ArrayList of reservations held by the given passenger
	 */
	public ArrayList<Reservation> FindPassengerReservations(Reservation reservation) {
		ArrayList<Reservation> reservations = new ArrayList<Reservation>();
		for (int idx = 0; idx < this.reservationList.size(); idx++) {
			// compare pointers to passenger objects here
			if (this.reservationList.get(idx).getPassenger().getEmailId().equalsIgnoreCase(reservation.getPassenger().getEmailId())
					|| 	this.reservationList.get(idx).getReservationNo().equals(reservation.getReservationNo())) 
				{
				reservations.add(this.reservationList.get(idx));
			}
		}
		return reservations;
		
		
	}
	/**
	 * Returns an ArrayList of passenger in waiting list
	 */
	public ArrayList<Passenger> FindPassengerWaiting(Passenger passenger) {
		ArrayList<Passenger> waiting = new ArrayList<Passenger>();
		if(this.waitingList!= null){
			for (int idx = 0; idx < this.waitingList.size(); idx++) {
				// compare pointers to passenger objects here
				if (this.waitingList.get(idx).getEmailId().equalsIgnoreCase(passenger.getEmailId())) {
					waiting.add(this.waitingList.get(idx));
				}
			}
		}
		return waiting;
		
	}

	/**
	 * view flight waiting list
	 */
	public ArrayList<Passenger> viewWaitingList() {
		if(this.waitingList == null)
		{
			this.waitingList = new ArrayList<Passenger>();
		}
		return this.waitingList;
	}

	/**
	 * View the all available seats in the flight
	 */
	public ArrayList<String> viewAvailableSeats() {
		ArrayList<String> availableSeats = new ArrayList<String>();
		String seatNo;
		for (int idx = 0; idx < this.maxRows; idx++)
		{
			for (int idy = 0; idy < this.maxSeatPerRow; idy++)
			{
				if(this.seatArray[idx][idy] == null)
				{
					seatNo = Integer.toString(idx+1) + cols.charAt(idy);
					availableSeats.add(seatNo);
				}
			}
			
		}
		return availableSeats;
	}
	

	 /**
	 * check if specific seat is available
	 * return true if available
	 */
	 public boolean checkSeatAvailability(int row, int seatNumber) {
	        boolean result = false;
	        /* if specific seat is not reserved the passengers name is null */
	        result = (getSeatArray()[row][seatNumber] == null);

	        return result;
	    }
	 

	 /**
	 * check if specific seat is available
	 * return true if available
	 */
	 public boolean checkSeatAvailability(Seat objSeat) {
	        boolean result = false;
	        getSeatLocationInArray(objSeat);
	        /* if specific seat is not reserved the passengers name is null */
	        result = (getSeatArray()[rowNumber][columnnumber] == null);

	        return result;
	    }
	 
	 /**
	 * check if at least one seat is available in flight
	 * return true if available
	 */
	 public boolean checkSeatAvailability() {
			boolean isSeatAvailable  = false;
			for (int idx = 0; idx < this.maxRows; idx++)
			{
				for (int idy = 0; idy < this.maxSeatPerRow; idy++)
				{
					if(this.seatArray[idx][idy] == null)
					{
						isSeatAvailable = true;
						break;
					}
				}
				
			}
			return isSeatAvailable;
		}
	
	 /**
	 * makes new reservation
	 * Adds passenger to reservation list and assign seat to passenger
	 */
	public boolean makeReservation(Reservation objRes) {
		if (reservationList == null)
		{
			reservationList = new ArrayList<Reservation>();
		}
		reservationList.add(objRes);
		assignSeatToPassenger(objRes);

		try {
			serializeFlight(this);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return true;
	}
	
	/**
	 * Assign seat to the passenger if seat is available
	 * 
	 */
	public void assignSeatToPassenger(Reservation objRes)
	{	
		getSeatLocationInArray(objRes.getSeat());
		if(checkSeatAvailability(rowNumber,columnnumber))
		{
			seatArray[rowNumber][columnnumber] = objRes.getPassenger();
			seatsLeft = seatsLeft-1;
		}
	
	}
	
	/**
	 * Remove current reservation by removing passenger from seat
	 * Decrement no of seats left
	 */
	public void removePassenger(Reservation objRes)
	{	
		getSeatLocationInArray(objRes.getSeat());
			
		seatArray[rowNumber][columnnumber] = null;
		seatsLeft = seatsLeft+1;
	
	}
	
	/**
	 * Takes Seat object and returns Row and column Number 
	 * which gives seat location in array
	 */
	public void getSeatLocationInArray(Seat objSeat)
	{
		rowNumber = Integer.parseInt(objSeat.getNumber().substring(0, 1))-1 ;
		colName=  objSeat.getNumber().substring(1);
		columnnumber = cols.indexOf(colName);
	}
	
	/**
	 * Adds passenger to waiting list when no seats are available in flight
	 */
	public boolean addPassengerToWaitingList(Passenger objPassenger)
	{
		if(waitingList == null)
		{
			waitingList = new ArrayList<Passenger>();
		}
		waitingList.add(objPassenger);
		try {
			serializeFlight(this);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return true;
	}
	
	/**
	 * Remove current reservation and make new reservation with the new seat
	 * If new seat is not available, keep old seat and return false
	 */
	public boolean cancelReservation(Reservation objRes) {
		if(reservationList != null && reservationList.contains(objRes))
		{
			reservationList.remove(objRes);
			removePassenger(objRes);
			
			//add person from waiting list to reservation
			if(waitingList != null){
				if(waitingList.size() > 0)
				{
					Passenger objPass = (Passenger) waitingList.get(0);
					Reservation objResAdd = new Reservation(Reservation.getNextReservationNo(), objPass, objRes.getSeat());
					
					makeReservation(objResAdd);
					waitingList.remove(objPass);
				}
			}
			
			try {
				serializeFlight(this);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		
		return true;
	}
	
	public static void serializeFlight(Flight objFlight) throws IOException
	{
		try
		{
			objFlight.currentReservationNo = Reservation.reservationNumber;
			flightSerialization.serialize(fileName, objFlight);
			
		}
		catch(IOException ex)
		{
			
		}
	}
	
	public static Flight deserializeFlight() throws OptionalDataException, ClassNotFoundException, IOException
	{
		Flight objFlight = null;
		try
		{
			objFlight = (Flight) flightSerialization.deserialize(fileName);
		
			Reservation.reservationNumber = objFlight.currentReservationNo;
		}
		catch(Exception ex)
		{
			
		}
		return objFlight;
	}
		
	/**
	 * @param args
	 */
	public static void main(String[] args) {

	}

}



/*reservationList = new ArrayList<Reservation>();
reservationList.add(new Reservation("1234", new Passenger("abc", "abc@gmail.com", "508-456-8797", "test"), new Seat("1A", false)));
reservationList.add(new Reservation("5677", new Passenger("test", "test@gmail.com", "508-323-8797", "CA"), new Seat("1B", false)));
reservationList.add(new Reservation("9876", new Passenger("pri", "@gmail.com", "233-987-5678", "fremont"), new Seat("1C", false)));

return reservationList;*/

/*waitingList = new ArrayList<Passenger>();
waitingList.add(new Passenger("abc", "abc@gmail.com", "508-456-8797", "test"));
waitingList.add(new Passenger("test", "test@gmail.com", "508-323-8797", "CA"));
waitingList.add(new Passenger("pri", "@gmail.com", "233-987-5678", "fremont"));

return waitingList;*/